package xin.yangshuai.forest01.interceptor;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.TypeReference;
import com.dtflys.forest.converter.ForestEncoder;
import com.dtflys.forest.exceptions.ForestRuntimeException;
import com.dtflys.forest.http.*;
import com.dtflys.forest.http.body.NameValueRequestBody;
import com.dtflys.forest.http.body.ObjectRequestBody;
import com.dtflys.forest.interceptor.Interceptor;
import com.dtflys.forest.reflection.ForestMethod;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public class SimpleInterceptor<T> implements Interceptor<T> {

    private final static Logger log = LoggerFactory.getLogger(SimpleInterceptor.class);

    /**
     * 该方法在被调用时，并在beforeExecute前被调用
     *
     * @Param request Forest请求对象
     * @Param args 方法被调用时传入的参数数组
     */
    @Override
    public void onInvokeMethod(ForestRequest req, ForestMethod method, Object[] args) {
        log.info("on invoke method");
        // req 为Forest请求对象，即 ForestRequest 类实例
        // method 为Forest方法对象，即 ForestMethod 类实例
        // addAttribute作用是添加和Forest请求对象以及该拦截器绑定的属性
        addAttribute(req, "A", "value1");
        addAttribute(req, "B", "value2");
    }

    /**
     * 在请求体数据序列化后，发送请求数据前调用该方法
     * 默认为什么都不做
     * 注: multlipart/data类型的文件上传格式的 Body 数据不会调用该回调函数
     *
     * @param request     Forest请求对象
     * @param encoder     Forest转换器
     * @param encodedData 序列化后的请求体数据
     */
    @Override
    public byte[] onBodyEncode(ForestRequest request, ForestEncoder encoder, byte[] encodedData) {
        // request: Forest请求对象
        // encoder: 此次转换请求数据的序列化器
        // encodedData: 序列化后的请求体字节数组
        // 返回的字节数组将替换原有的序列化结果
        // 默认不做任何处理，直接返回参数 encodedData
        return encodedData;
    }


    /**
     * 该方法在请求发送之前被调用, 若返回false则不会继续发送请求
     *
     * @Param request Forest请求对象
     */
    @Override
    public boolean beforeExecute(ForestRequest req) {
        log.info("invoke Simple beforeExecute");
        // 执行在发送请求之前处理的代码
        req.addHeader("accessToken", "11111111");  // 添加Header
        req.addQuery("username", "foo");  // 添加URL的Query参数

        // 设置日期格式
        String dateFormat = "yyyy-MM-dd HH:mm:ss";

        Map<String, String> map = null;
        Map<String, Object> tempMap = null;

        if (StringUtils.equalsIgnoreCase("POST", req.getType().getName())) {
            System.out.println("POST");
            ForestBody body = req.getBody();
            for (ForestRequestBody forestRequestBody : body) {
                if (forestRequestBody instanceof ObjectRequestBody) {
                    Object object = ((ObjectRequestBody) forestRequestBody).getObject();
                    String str = JSON.toJSONString(object, dateFormat, JSONWriter.Feature.WriteLongAsString);
                    map = JSON.parseObject(str, new TypeReference<Map<String, String>>() {
                    });
                    break;
                }
                if (forestRequestBody instanceof NameValueRequestBody) {
                    String name = ((NameValueRequestBody) forestRequestBody).getName();
                    Object value = ((NameValueRequestBody) forestRequestBody).getValue();

                    if (tempMap == null) {
                        tempMap = new HashMap<>();
                    }
                    tempMap.put(name, value);
                }
            }
        }
        if (StringUtils.equalsIgnoreCase("GET", req.getType().getName())) {
            System.out.println("GET");
            ForestQueryMap queryMap = req.getQuery();
            for (Map.Entry<String, Object> stringObjectEntry : queryMap.entrySet()) {
                String entryKey = stringObjectEntry.getKey();
                Object value = stringObjectEntry.getValue();

                if (tempMap == null) {
                    tempMap = new HashMap<>();
                }
                tempMap.put(entryKey, value);
            }
        }

        if (map == null && tempMap != null) {
            String str = JSON.toJSONString(tempMap, dateFormat, JSONWriter.Feature.WriteLongAsString);
            map = JSON.parseObject(str, new TypeReference<Map<String, String>>() {
            });
        }

        System.out.println(map);
        System.out.println(JSON.toJSONString(map));
        System.out.println("-----------------------------------");

        return true;  // 继续执行请求返回true
    }

    /**
     * 该方法在请求成功响应时被调用
     */
    @Override
    public void onSuccess(T data, ForestRequest req, ForestResponse res) {
        log.info("invoke Simple onSuccess");
        // 执行成功接收响应后处理的代码
        int status = res.getStatusCode(); // 获取请求响应状态码
        String content = res.getContent(); // 获取请求的响应内容
//        String result = (String) data;  // data参数是方法返回类型对应的返回数据结果,注意需要视情况修改对应的类型否则有可能出现类转型异常
//        result = (String) res.getResult(); // getResult()也可以获取返回的数据结果
//        res.setResult("修改后的结果: " + result);  // 可以修改请求响应的返回数据结果

        // 使用getAttributeAsString取出属性，这里只能取到与该Forest请求对象，以及该拦截器绑定的属性
        String attrValue1 = getAttributeAsString(req, "A1");

    }

    /**
     * 该方法在请求发送失败时被调用
     */
    @Override
    public void onError(ForestRuntimeException ex, ForestRequest req, ForestResponse res) {
        log.info("invoke Simple onError");
        // 执行发送请求失败后处理的代码
        int status = res.getStatusCode(); // 获取请求响应状态码
        String content = res.getContent(); // 获取请求的响应内容
        String result = (String) res.getResult(); // 获取方法返回类型对应的返回数据结果
    }

    /**
     * 该方法在请求发送之后被调用
     */
    @Override
    public void afterExecute(ForestRequest req, ForestResponse res) {
        log.info("invoke Simple afterExecute");
        // 执行在发送请求之后处理的代码
        int status = res.getStatusCode(); // 获取请求响应状态码
        String content = res.getContent(); // 获取请求的响应内容
        String result = (String) res.getResult(); // 获取方法返回类型对应的最终数据结果
    }
}

